package com.example.martian.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.martian.config.util.RedisUtils;
import com.example.martian.pojo.InfuraConfig;
import okhttp3.Credentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthBlockNumber;
import org.web3j.protocol.http.HttpService;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class Web3JConfig {

    @Autowired
    private static Web3j web3j;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    RestTemplate restTemplate;



    @Autowired
    private ExchangeRateUtils exchangeRateUtils;

    private final static String DEF_AUTH = "Authorization";

    private static final Logger LOG = (Logger) LoggerFactory.getLogger(Web3JConfig.class);

    private static final String URL = "https://chain.api.btc.com/v3/block/latest";

    private static final String COINURL = "https://api-prod.poolin.com/api/public/v2/basedata/chain/difficulty/stat_by_day?";

    private static final Integer btcUnit = 2100000;

    @Bean
    public Web3j web3j(InfuraConfig infuraConfig) {

        HttpService httpService = new HttpService(infuraConfig.getUrl());
        String credential = Credentials.basic(infuraConfig.getProjectId(), infuraConfig.getProjectSecret());
        httpService.addHeader(DEF_AUTH, credential);
        Web3j web3 = Web3j.build(httpService);
        return web3;
    }

    /**
     * 以太坊区块数量
     * @return
     */
//    @Scheduled(cron = "0/5 * * * * ?")
    public static BigInteger getEthBlockNumber() {
        EthBlockNumber send = new EthBlockNumber();
        try {
            send = web3j.ethBlockNumber().send();
        } catch (IOException e) {
            LOG.warn("请求区块链信息异常 >> 区块数量,{}", e);
        }
        System.out.println(send.getBlockNumber());
        return send.getBlockNumber();
    }

    /**
     * 比特币区块数量
     * @return
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void getBtcBlockEarnings() throws IOException {
        JSONObject jsonObject = exchangeRateUtils.exchangeRate(URL);
        JSONObject object = jsonObject.getJSONObject("data");
        Integer height = Integer.parseInt(object.get("height").toString());
        Double btcReward = Double.parseDouble(redisUtils.getDataFromCache("btcReward").toString());
        if (height / btcUnit == 64){
            redisUtils.setDataToCache("btcReward",0);
        } else if (height % btcUnit == 0){
            btcReward = BigDecimalUtils.div(btcReward,2);
            redisUtils.setDataToCache("btcReward",btcReward);
        }
    }

    //获取btc挖矿难度
    public BigDecimal getBtcdifficulty(String coin) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,-2);
        Date time = calendar.getTime();
        //转换时间戳
        String format = dateFormat.format(time);
        Date parse = dateFormat.parse(format);
        long parseTime = parse.getTime()/1000;
        String param = "coin_tag="+coin+"&start_ts="+parseTime;
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<JSONObject> forEntity = restTemplate.exchange(COINURL + param, HttpMethod.GET, entity, JSONObject.class);
        JSONObject data = forEntity.getBody().getJSONObject("data");
        JSONObject dataJSONObject = data.getJSONObject(format);
        BigDecimal difficulty = new BigDecimal(dataJSONObject.get("avg_difficulty").toString());
        return difficulty;
    }

    //BTC收益计算
    public Object getBtcEarningsByDay(String coin) throws ParseException {
        Double btcReward = Double.parseDouble(redisUtils.getDataFromCache("btcReward").toString());
        System.out.println("btcReward"+btcReward);
        BigDecimal btcdifficulty = getBtcdifficulty(coin);
        double pow = Math.pow(2, 32);//算力
        System.out.println(pow);
        BigDecimal bigDecimal = new BigDecimal(1e12 * 86400 * btcReward);
        System.out.println(bigDecimal);
        BigDecimal decimal = btcdifficulty.multiply(BigDecimal.valueOf(pow));
        System.out.println(decimal);
        String scale = bigDecimal.divide(decimal,10,BigDecimal.ROUND_HALF_UP).toPlainString();
        return scale;
    }

    //获取eth挖矿难度
    public BigDecimal getEthdifficulty(String coin) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,- 2);
        Date time = calendar.getTime();
        //转换时间戳
        String format = dateFormat.format(time);
        Date parse = dateFormat.parse(format);
        long parseTime = parse.getTime()/1000;
        String param = "coin_tag="+coin+"&start_ts="+parseTime;
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<JSONObject> forEntity = restTemplate.exchange(COINURL + param, HttpMethod.GET, entity, JSONObject.class);
        JSONObject data = forEntity.getBody().getJSONObject("data");
        JSONObject dataJSONObject = data.getJSONObject(format);
        System.out.println(dataJSONObject);
        BigDecimal difficulty = new BigDecimal(dataJSONObject.get("avg_difficulty").toString());
        return difficulty;
    }

//    public Object earningsAndCloudDay(String coin){
//        if (coin.equals("BTC")){
//            Object btcEarningsByDay = web3JConfig.getBtcEarningsByDay(coin);
//            //每TH/S  * 算力T = 币种单日收益
//            BigDecimal multiplyHashrateBtc = new BigDecimal(btcEarningsByDay.toString()).multiply(new BigDecimal(78));
//            //算力 * 币价 = 收益  日收益
//            BigDecimal dailyEarnings = multiplyHashrateBtc.multiply(CNY);
//            BigDecimal BackToDay = new BigDecimal(map.get("mill_cost").toString()).
//                    divide(dailyEarnings,0,BigDecimal.ROUND_HALF_UP);
//            jsonObject.put("Back_tothe",BackToDay);//计算得出
//            BigDecimal decimal = new BigDecimal(earningsDay.toString()).multiply(new BigDecimal(78));
//            jsonObject.put("earnings",decimal);
//        }
//        if (coin.equals("ETH")){
//            Object ethEarningsByDay = getEthEarningsByDay(coin);
//            //每TH/S  * 算力T = 币种单日收益
//            BigDecimal multiplyHashrate = new BigDecimal(ethEarningsByDay.toString()).multiply(new BigDecimal(400));
//            //算力 * 币价 = 收益  日收益
//            BigDecimal dailyEarnings = multiplyHashrate.multiply(CNY);
//            //回本周期
//            BigDecimal Back_tothe = new BigDecimal(map.get("mill_cost").toString()).divide(dailyEarnings,0,BigDecimal.ROUND_HALF_UP);
//            jsonObject.put("Back_tothe",Back_tothe);//计算得出
//            BigDecimal decimal = new BigDecimal(earningsDay.toString()).multiply(new BigDecimal(400));
//            jsonObject.put("earnings",decimal);
//        }
//    }
}
